/*******************************************************************
 *
 * Copyright (C), 2021-2022, Letstrong, All rights reserved.
 *
 * Author      : 
 * Create Time : 2021-01-05
 * Version     : v0.1
 * Description : 
 *******************************************************************/
 
/*----------------------------Head file----------------------------*/
#include "gap.h"
#include "aes.h"
#include "sha256.h"
#include "cbc_mode.h"
#include "crypto_utils.h"
#include "user_config.h"
#include "ais.h"
#include "ais_task.h"
#include "ais_protocol.h"
#include "app_global_data.h"

#define AIS_PROTO_LOG_EN		1

#if AIS_PROTO_LOG_EN
#include "log.h"
#define AIS_PROTO_LOG			LOG_DEBUG
#else
#define AIS_PROTO_LOG(...)
#endif

#if(AIS_TMALL_GENIE_ENABLE)

/*----------------------------macro file---------------------------*/
#define AIS_BLE_KEY_LEN		16

#define AIS_AES_IV_VECTOR_STR	"123aqwed#*$!(4ju"

#define AIS_VM_ATTR_SKIP_MISS_CNT		0x06C0
#define AIS_VM_ATTR_CUR_SKIP_FREQ		0x06C1
#define AIS_VM_ATTR_AVG_SKIP_FREQ		0x06C2
#define AIS_VM_ATTR_MAX_SKIP_FREQ		0x06C3
#define AIS_VM_ATTR_MAX_CONTI_SKIP		0x06C4
#define AIS_VM_ATTR_SKIP_CNT_SUM		0x06C5

/*----------------------------type define--------------------------*/

/*----------------------------var define---------------------------*/
static uint8_t ais_rx_msg_id;
static uint8_t ais_ble_key[AIS_BLE_KEY_LEN];

/*-------------------------func declaration------------------------*/

/*-----------------------------------------------------------------*/


/*SHA256 TEST:
SHA256 INPUT: abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq	//56bytes
SHA256 OUTPUT:
{ 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
  0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
  0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
  0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },*/
int app_ais_auth_ble_key_generate(uint8_t *random, uint8_t r_len, uint8_t *key, uint8_t k_len)
{
	//uint8_t buf[71] = "1234567890123456,0065a1d4,18146c1012c8,682f0ea21a1816182b178ca71e80513b";
	uint8_t buf[71] = "1234567890123456,00657609,18146c115051,1314ecf3fc6289b3c87a34abb8090eef";	//6649353	//Note: all use lower-case letter!!!
	uint8_t sha256sum[32];
	TCSha256State_stuct ctx;

	if(r_len != 16 && k_len != 16) {
		AIS_PROTO_LOG("key len or random len err\n");
		return TC_CRYPTO_FAIL;
	}
	
	memcpy(buf, random, r_len);
	/*AIS_PROTO_LOG("buf: ");
	for(uint8_t i=0;i<sizeof(buf);i++) {
		AIS_PROTO_LOG("%x, ", buf[i]);
	}
	AIS_PROTO_LOG("\n");*/
	//AIS_PROTO_LOG("%s\n", buf);
	
	if(TC_CRYPTO_SUCCESS != tc_sha256_init(&ctx)) {
		AIS_PROTO_LOG("tc_sha256_init fail.\n");
		return TC_CRYPTO_FAIL;
	}
	if(TC_CRYPTO_SUCCESS != tc_sha256_update(&ctx, buf, sizeof(buf))) {
		AIS_PROTO_LOG("tc_sha256_update fail.\n");
		return TC_CRYPTO_FAIL;
	}
	if(TC_CRYPTO_SUCCESS != tc_sha256_final(sha256sum, &ctx)) {
		AIS_PROTO_LOG("tc_sha256_final fail.\n");
		return TC_CRYPTO_FAIL;
	}

	memcpy(key, sha256sum, k_len);
	
	return TC_CRYPTO_SUCCESS;
}


int app_ais_aes_encrypt(uint8_t *out, uint8_t out_len, uint8_t *in, uint8_t in_len)
{
	uint8_t iv[TC_AES_BLOCK_SIZE] = AIS_AES_IV_VECTOR_STR;
	TCAesKeySched_struct ctx;
	
	if(TC_AES_BLOCK_SIZE != out_len || TC_AES_BLOCK_SIZE != in_len)
		return TC_CRYPTO_FAIL;

	memset(out, 0, out_len);
	if(TC_CRYPTO_SUCCESS != tc_aes128_set_encrypt_key(&ctx, ais_ble_key)) {
		AIS_PROTO_LOG("tc_aes128_set_encrypt_key fail.\n");
		return TC_CRYPTO_FAIL;
	}
	if(TC_CRYPTO_SUCCESS != tc_cbc_mode_encrypt(out, out_len, in, in_len, iv, &ctx)) {
		AIS_PROTO_LOG("tc_cbc_mode_encrypt fail.\n");
		return TC_CRYPTO_FAIL;
	}
	
	AIS_PROTO_LOG("\ncipher: ");
	for(uint8_t i=0;i<out_len;i++) {
		AIS_PROTO_LOG("%x, ", out[i]);
	}
	AIS_PROTO_LOG("\n");
	
	return TC_CRYPTO_SUCCESS;
}


int app_ais_aes_decrypt(uint8_t *out, uint8_t out_len, uint8_t *in, uint8_t in_len)
{
	uint8_t iv[TC_AES_BLOCK_SIZE] = AIS_AES_IV_VECTOR_STR;
	TCAesKeySched_struct ctx;
	
	if(TC_AES_BLOCK_SIZE != out_len || TC_AES_BLOCK_SIZE != in_len)
		return TC_CRYPTO_FAIL;

	memset(out, 0, out_len);
	if(TC_CRYPTO_SUCCESS != tc_aes128_set_decrypt_key(&ctx, ais_ble_key)) {
		AIS_PROTO_LOG("tc_aes128_set_decrypt_key fail.\n");
		return TC_CRYPTO_FAIL;
	}
	if(TC_CRYPTO_SUCCESS != tc_cbc_mode_decrypt(out, out_len, in, in_len, iv, &ctx)) {
		AIS_PROTO_LOG("tc_cbc_mode_decrypt fail.\n");
		return TC_CRYPTO_FAIL;
	}
	
	AIS_PROTO_LOG("\nplain: ");
	for(uint8_t i=0;i<out_len;i++) {
		AIS_PROTO_LOG("%x, ", out[i]);
	}
	AIS_PROTO_LOG("\n");
	
	return TC_CRYPTO_SUCCESS;
}


static bool ais_indicate_trans(uint8_t cmd, const uint8_t* pData, uint16_t len, bool encrypt)
{
	if(len > AIS_FRAME_DATA_MAX_SIZE)
		return false;

	struct ais_ind_upd_req indic;
	ais_frame_t *buf = (ais_frame_t*)&indic.value;

	memset(&indic, 0, sizeof(indic));

	AIS_PROTO_LOG("ais_rx_msg_id: %d.\n", ais_rx_msg_id);
	buf->msg.id = ais_rx_msg_id;
	buf->msg.security = encrypt;
	buf->cmd = cmd;
	buf->frame.seq = 0;
	buf->frame.total_num = 0;
	
	if(encrypt) {
		indic.len = 20;
		buf->frame_len = AIS_FRAME_DATA_MAX_SIZE;
		uint8_t temp[16];
		memset(temp, 0, sizeof(temp));
		memcpy(temp, pData, len);
		app_ais_aes_encrypt(buf->data, AIS_FRAME_DATA_MAX_SIZE, temp, sizeof(temp));
	}
	else {
		indic.len = len + 4;
		buf->frame_len = len;
		memcpy(buf->data, pData, len);
	}

	ais_indicate_data(&indic);

	AIS_PROTO_LOG("\nais_indicate: ");
	for(uint8_t i=0;i<indic.len;i++) {
		AIS_PROTO_LOG("%x, ", indic.value[i]);
	}
	AIS_PROTO_LOG("\n");
	
	return true;
}


void ble_ais_client_write_handle(const uint8_t *pData, uint8_t len)
{
	AIS_PROTO_LOG("ais_write_rsp: ");
	for(uint16_t i=0;i<len;i++) {
		AIS_PROTO_LOG("%x, ", pData[i]);
	}
	AIS_PROTO_LOG("\n");
	
	ais_frame_t *rx = (ais_frame_t*)pData;
	
	switch(rx->cmd)
	{
		case AIS_CMD_APP_AUTH_RANDOM: {
			AIS_PROTO_LOG("AIS_CMD_APP_AUTH_RANDOM.\n");
			ais_rx_msg_id = rx->msg.id;
			uint8_t cipher[16];
			if(TC_CRYPTO_SUCCESS != app_ais_auth_ble_key_generate(rx->data, AIS_FRAME_DATA_MAX_SIZE, ais_ble_key, sizeof(ais_ble_key)))
				return;
			if(TC_CRYPTO_SUCCESS != app_ais_aes_encrypt(cipher, sizeof(cipher), rx->data, rx->frame_len))
				return;
			ais_indicate_trans(AIS_CMD_DEV_AUTH_CIPHER, cipher, AIS_FRAME_DATA_MAX_SIZE, false);
		} break;
		
		
		case AIS_CMD_APP_AUTH_RESULT: {
			AIS_PROTO_LOG("AIS_CMD_APP_AUTH_RESULT.\n");
			ais_rx_msg_id = rx->msg.id;
			if(1 == rx->frame_len && AIS_RESULT_SUCCESS == rx->data[0]) {
				uint8_t ret = AIS_RESULT_SUCCESS;
				ais_indicate_trans(AIS_CMD_DEV_AUTH_RESULT, &ret, 1, false);
				AIS_PROTO_LOG("APP_AUTH_RESULT SUCCESS\n");
				
				//for test
				//osal_start_timerEx(BleMain_TaskID, BLE_DELAY_DISCONNECT_EVT, 3000);
			}
			else {
				AIS_PROTO_LOG("APP_AUTH_RESULT FAIL\n");
			}
		} break;
		
		
		case AIS_CMD_APP_BIND_OP: {
			AIS_PROTO_LOG("AIS_CMD_APP_BIND_OP.\n");
			ais_rx_msg_id = rx->msg.id;
			uint8_t plain[16];
			if(TC_CRYPTO_SUCCESS == app_ais_aes_decrypt(plain, sizeof(plain), rx->data, rx->frame_len)) {
				uint8_t ret = AIS_ACK;
				if(AIS_UNBIND == plain[0]) {
					AIS_PROTO_LOG("AIS_UNBIND\n");
					ais_indicate_trans(AIS_CMD_DEV_BIND_OP, &ret, 1, true);
				}
				else if(AIS_BIND_DONE == plain[0]) {
					AIS_PROTO_LOG("AIS_BIND_DONE\n");
					//app_ais_bind_state_adv_set(false);	//TODO: revert
					ais_indicate_trans(AIS_CMD_DEV_BIND_OP, &ret, 1, true);
					
					//for test
					//osal_start_timerEx(BleMain_TaskID, BLE_DELAY_DISCONNECT_EVT, 500);
				}
			}
		} break;
	}
}



void ais_upload_skip_disp_data(void)
{
	ais_skip_ret_t ret;

	if(BLE_CONN_TYPE_AIS != g_app_data.sys.ble_conn_type)
		return;
	
	//AIS_PROTO_LOG("ais_upload_skip_disp_data\n");
	memset((uint8_t*)&ret, 0, sizeof(ret));
	
	ret.mode = g_app_data.tmp.skip.mode;
	ret.trip_num = g_app_data.tmp.skip.trip_num;
	ret.sport_time = Tranverse16(g_app_data.tmp.skip.skip_sec_sum);
	ret.sport_count = Tranverse16(g_app_data.tmp.skip.skip_cnt_sum);
	
	ais_rx_msg_id = 0;
	ais_indicate_trans(AIS_CMD_DEV_UPLOAD, (uint8_t*)&ret, sizeof(ret), true);
}


void ais_upload_skip_result(void)
{
	ais_skip_ret_t ret;

	if(BLE_CONN_TYPE_AIS != g_app_data.sys.ble_conn_type)
		return;
	
	AIS_PROTO_LOG("ais_upload_skip_result\n");
	memset((uint8_t*)&ret, 0, sizeof(ret));
	
	ret.mode = g_app_data.tmp.skip.mode;
	ret.trip_num = g_app_data.tmp.skip.trip_num;
	ret.sport_time = Tranverse16(g_app_data.tmp.skip.skip_sec_sum);
	ret.sport_count = Tranverse16(g_app_data.tmp.skip.skip_cnt_sum);
	ret.max_num_consecutive = Tranverse16(g_app_data.tmp.skip.consecutive_skip_max_num);
	ret.highest_freq = Tranverse16(g_app_data.tmp.skip.freq_max);
	ret.avg_freq = Tranverse16(g_app_data.tmp.skip.freq_avg);
	
	ais_rx_msg_id = 0;
	ais_indicate_trans(AIS_CMD_DEV_UPLOAD, (uint8_t*)&ret, sizeof(ret), true);
}


#if 0
void ais_encrypt_test(void)
{
	uint8_t cipher[16];
	uint8_t plain[16] = "123";
	uint8_t ble_key[16] = "0000000000000000";
	uint8_t iv[16] = "0000000000000000";
	TCAesKeySched_struct ctx;
	
	memset(cipher, 0, sizeof(cipher));
	memset(&ctx, 0, sizeof(ctx));
	
	if(TC_CRYPTO_SUCCESS != tc_aes128_set_encrypt_key(&ctx, ble_key)) {
		AIS_PROTO_LOG("tc_aes128_set_encrypt_key fail.\n");
		return;
	}
	
	if(TC_CRYPTO_SUCCESS != tc_cbc_mode_encrypt(cipher, sizeof(cipher), plain, sizeof(plain), iv, &ctx)) {
		AIS_PROTO_LOG("tc_cbc_mode_encrypt fail.\n");
		return;
	}
	
	AIS_PROTO_LOG("cipher: ");
	for(uint8_t i=0;i<sizeof(cipher);i++) {
		AIS_PROTO_LOG("%x, ", cipher[i]);
	}
	AIS_PROTO_LOG("\n");
	
	if(TC_CRYPTO_SUCCESS != tc_cbc_mode_decrypt(plain, sizeof(plain), cipher, sizeof(cipher), iv, &ctx)) {
		AIS_PROTO_LOG("tc_cbc_mode_decrypt fail.\n");
		return;
	}
	
	AIS_PROTO_LOG("plain: ");
	for(uint8_t i=0;i<sizeof(plain);i++) {
		AIS_PROTO_LOG("%x, ", plain[i]);
	}
	AIS_PROTO_LOG("\n");
	
	/*uint8_t ble_key[16];
	uint8_t random[16] = {0xaa, 0x8d, 0x47, 0x9b, 0xb4, 0xf2, 0x46, 0x93, 0x9c, 0xdc, 0x8f, 0xd3, 0xe5, 0x5d, 0xf2, 0xa0};
	void app_ais_auth_ble_key_generate(uint8_t *random, uint8_t r_len, uint8_t *key, uint8_t k_len);
	app_ais_auth_ble_key_generate(random, sizeof(random), ble_key, sizeof(ble_key));*/
}
#endif

#endif	//#if(AIS_TMALL_GENIE_ENABLE)
